package org.ccay.security.entity;

import java.io.Serializable;

import org.ccay.security.annotation.SecurityPolicy;

/**
 * 权限
 * @author chaowangbang
 * @since 2017年2月5日
 */
public class Permission implements org.apache.shiro.authz.Permission,Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * 资源与操作的分割符
	 */
	public static final String RESOURCE_OPREATION_SPLIT_CHART = ":";

	/**
	 * 资源层级分隔符
	 */
	public static final String CLASSIFICATION_SPLIT_CHART = "|";

	/**
	 * 默认无参构造
	 */
	public Permission(){}
	/**
	 * 资源id
	 */
	private Long permissionId;
	/**
	 * 资源编码
	 */
	private String resourceCode;
	
	/**
	 * 资源的人工可读信息。可以通过<code>|</code>进行层级定义
	 */
	private String resourceName;

	/**
	 * 资源描述
	 */
	private String resourceDesc;

	/**
	 * 操作编码
	 */
	private String operationCode;

	/**
	 * 操作的人工可读信息
	 */
	private String operationName;
	
	/**
	 * 操作的具体描述
	 */
	private String operationDesc;
	
	/**
	 * 此资源及操作下的访问策略
	 */
	private SecurityPolicy policy;
	
	/**
	 * 此权限点绑定的URL
	 */
	private String bindingURL;
	/**
	 * 通过字符串构造Permission 格式为 资源编码:操作编码
	 * @param permission
	 */
	public Permission(String permission) {
		if (null == permission || permission.trim().length() == 0) {
			throw new IllegalArgumentException("参数不能 为空");
		}
		String[] parts = permission.split(RESOURCE_OPREATION_SPLIT_CHART);
		if (parts.length != 2) {
			throw new IllegalArgumentException("权限字符串必须使用 资源编码:操作编码的形式！");
		}
		resourceCode = parts[0];
		operationCode = parts[1];
		checkArgs(resourceCode, operationCode);
	}
	

	/**
	 * 构建最少必要属性的Permission
	 * @param resourceCode 资源编码
	 * @param operationCode 操作编码
	 */
	public Permission(String resourceCode, String operationCode) {
		checkArgs(resourceCode, operationCode);
		this.resourceCode = resourceCode;
		this.operationCode = operationCode;
	}

	/**
	 * 构建所有属性的Permission
	 * @param resourceCode
	 * @param resourceName
	 * @param resourceDesc
	 * @param operationCode
	 * @param operationName
	 * @param operationDesc
	 * @param policy
	 */
	public Permission(String resourceCode,String resourceName, String resourceDesc,
			String operationCode, String operationName,String operationDesc,SecurityPolicy policy) {
		checkArgs(resourceCode, operationCode);
		this.resourceCode = resourceCode;
		this.resourceName = resourceName;
		this.resourceDesc = resourceDesc;
		
		this.operationCode = operationCode;
		this.operationName = operationName;
		this.operationDesc = operationDesc;
		
		this.policy = policy;
	}
	
	/**
	 * 校验必须属性
	 * @param resourceCode
	 * @param operationCode
	 */
	private void checkArgs(String resourceCode, String operationCode){
		if (null == resourceCode || resourceCode.trim().length() == 0
				|| null == operationCode || operationCode.trim().length() == 0) {
			throw new IllegalArgumentException("资源编码与操作编码不能为空！");
		}
	}
	
	/**
	 * 返回Permission的字符串表示
	 * @return
	 */
	public String getPermissionString(){
		return resourceCode+RESOURCE_OPREATION_SPLIT_CHART+operationCode;
	}

	/* (non-Javadoc)
	 * @see org.apache.shiro.authz.Permission#implies(org.apache.shiro.authz.Permission)
	 */
	@Override
	public boolean implies(org.apache.shiro.authz.Permission p) {
		if (null == p) {
			return false;
		}
		if (!(p instanceof Permission)) {
			return false;
		}
		Permission other = (Permission) p;
		if (resourceCode.equals(other.getResourceCode())
				&& operationCode.equals(other.getOperationCode())) {
			return true;
		}
		return false;
	}
	

	public Long getPermissionId() {
		return permissionId;
	}


	public void setPermissionId(Long permissionId) {
		this.permissionId = permissionId;
	}

	public String getResourceCode() {
		return resourceCode;
	}

	public void setResourceCode(String resourceCode) {
		this.resourceCode = resourceCode;
	}

	public String getOperationCode() {
		return operationCode;
	}

	public void setOperationCode(String operationCode) {
		this.operationCode = operationCode;
	}

	public String getOperationDesc() {
		return operationDesc;
	}

	public void setOperationDesc(String operationDesc) {
		this.operationDesc = operationDesc;
	}

	public String getResourceDesc() {
		return resourceDesc;
	}

	public void setResourceDesc(String resourceDesc) {
		this.resourceDesc = resourceDesc;
	}

	public String getResourceName() {
		return resourceName;
	}

	public void setResourceName(String resourceName) {
		this.resourceName = resourceName;
	}

	public String getOperationName() {
		return operationName;
	}

	public void setOperationName(String operationName) {
		this.operationName = operationName;
	}


	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((operationCode == null) ? 0 : operationCode.hashCode());
		result = prime * result
				+ ((resourceCode == null) ? 0 : resourceCode.hashCode());
		return result;
	}


	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Permission other = (Permission) obj;
		if (operationCode == null) {
			if (other.operationCode != null)
				return false;
		} else if (!operationCode.equals(other.operationCode))
			return false;
		if (resourceCode == null) {
			if (other.resourceCode != null)
				return false;
		} else if (!resourceCode.equals(other.resourceCode))
			return false;
		return true;
	}

	@Override
	public String toString() {
		StringBuilder builder = new StringBuilder();
		builder.append("Permission [resourceCode=");
		builder.append(resourceCode);
		builder.append(", resourceName=");
		builder.append(resourceName);
		builder.append(", resourceDesc=");
		builder.append(resourceDesc);
		builder.append(", operationCode=");
		builder.append(operationCode);
		builder.append(", operationName=");
		builder.append(operationName);
		builder.append(", operationDesc=");
		builder.append(operationDesc);
		builder.append(", policy=");
		builder.append(policy);
		builder.append("]");
		return builder.toString();
	}


	public String getBindingURL() {
		return bindingURL;
	}

	public void setBindingURL(String bindingURL) {
		this.bindingURL = bindingURL;
	}
}
